package impl.gui;

import impl.core.UDecideManager;
import impl.gui.listeners.UDecideGUIListener;
import impl.gui.listeners.UtilityAssertionListListener;
import impl.gui.util.UDecideGUIElementFactory;
import impl.gui.util.SmartScroller;
import impl.gui.util.UtilityAssertionRenderer;
import impl.util.UtilityAssertion;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Collection;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;

public class UBoxPanel extends JPanel {

	// trinity of panels (uBox control, utility assertion control, utility
	// assertion content)
	private JPanel								uBoxControlBar;
	private JPanel								utilityAssertionPanel;

	// uBox control panel components
	private JButton								clearUBoxButton;
	private JButton								loadUBoxButton;
	private JButton								saveUBoxButton;

	private JLabel								currentUBoxLabel;

	// utility assertion panel components
	private JButton								addUtilityAssertionButton;
	private JButton								removeUtilityAssertionButton;
	private static JButton						startCalculationButton;
	private JCheckBox							koncludeFastMode;

	private DefaultListModel<UtilityAssertion>	uAssertionListModel;
	private JList<UtilityAssertion>				uAssertionList;

	private JScrollPane							uAssertionScrollPane;

	public UBoxPanel() {
		buildUBoxControlBar();
		buildUtilityAssertionPanel();

		this.setLayout(new BorderLayout());

		this.add(this.uBoxControlBar, BorderLayout.NORTH);
		this.add(this.utilityAssertionPanel, BorderLayout.CENTER);
	}

	public void addUtilityAssertion(UtilityAssertion utilityAssertion) {
		this.uAssertionListModel.addElement(utilityAssertion);
	}

	public void setUtilityAssertions(Collection<UtilityAssertion> utilityAssertions) {
		this.uAssertionListModel.clear();

		for (UtilityAssertion u : utilityAssertions) {
			this.uAssertionListModel.addElement(u);
		}
	}

	public void removeAllUtilityAssertions() {
		this.uAssertionListModel.clear();
	}

	public void removeUtilityAssertion(Collection<UtilityAssertion> uAssertions) {
		for (UtilityAssertion u : uAssertions) {
			this.uAssertionListModel.removeElement(u);
		}
	}

	public static void enableComputation(boolean b) {
		startCalculationButton.setEnabled(b);
	}

	public void setUtilityAssertionRenderer(UtilityAssertionRenderer utilityAssertionRenderer) {
		this.uAssertionList.setCellRenderer(utilityAssertionRenderer);
		this.uAssertionList.repaint();
	}

	public void clearUtilityAssertionSelections() {
		this.uAssertionList.getSelectionModel().clearSelection();
		this.uAssertionList.repaint();
	}

	public UtilityAssertion getSelectedUtilityAssertion() {
		return this.uAssertionList.getSelectedValue();
	}

	public Collection<UtilityAssertion> getSelectedUtilityAssertions() {
		return this.uAssertionList.getSelectedValuesList();
	}

	public void utilityAssertionSelected(boolean enabled) {
		this.removeUtilityAssertionButton.setEnabled(enabled);
	}

	public void setCurrentUBoxPath(String path) {
		this.currentUBoxLabel.setText(path);
	}

	private void buildUBoxControlBar() {
		this.clearUBoxButton = new JButton("Clear uBox");
		this.clearUBoxButton.setActionCommand("clearUBox");
		this.clearUBoxButton.addActionListener(UDecideGUIListener.getInstance());
		this.loadUBoxButton = new JButton("Open uBox...");
		this.loadUBoxButton.setActionCommand("loadUBox");
		this.loadUBoxButton.addActionListener(UDecideGUIListener.getInstance());
		this.saveUBoxButton = new JButton("Save uBox As...");
		this.saveUBoxButton.setActionCommand("saveUBox");
		this.saveUBoxButton.addActionListener(UDecideGUIListener.getInstance());

		this.currentUBoxLabel = new JLabel("Unsaved uBox");
		this.currentUBoxLabel.setBorder(UDecideGUIElementFactory.getBorder("Current uBox file path"));

		this.uBoxControlBar = new JPanel();
		// this.uBoxControlBar.setFloatable(false);
		this.uBoxControlBar.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.BOTH;
		c.gridx = 0;
		c.gridy = 0;
		c.weighty = 1.0;
		this.uBoxControlBar.add(this.clearUBoxButton, c);
		c.gridx = 1;
		this.uBoxControlBar.add(this.loadUBoxButton, c);
		c.gridx = 2;
		c.gridwidth = 5;
		c.weightx = 1.0;
		this.uBoxControlBar.add(this.currentUBoxLabel, c);
		c.weightx = 0.0;
		c.gridx = 7;
		this.uBoxControlBar.add(this.saveUBoxButton, c);
	}

	private void buildUtilityAssertionPanel() {
		this.utilityAssertionPanel = new JPanel(new BorderLayout());

		this.addUtilityAssertionButton = UDecideGUIElementFactory.getButton("+", "showUAssertionDialog");
		this.addUtilityAssertionButton.addActionListener(UDecideGUIListener.getInstance());
		this.removeUtilityAssertionButton = UDecideGUIElementFactory.getButton("-", false, "removeUAssertions");
		this.removeUtilityAssertionButton.addActionListener(UDecideGUIListener.getInstance());
		UBoxPanel.startCalculationButton = UDecideGUIElementFactory.getButton("Calculate Utilities", false, "startCalculation");
		UBoxPanel.startCalculationButton.addActionListener(UDecideGUIListener.getInstance());
		this.koncludeFastMode = new JCheckBox("Konclude Hack", UDecideManager.fastKoncludeMode);
		this.koncludeFastMode.setHorizontalAlignment((int) CENTER_ALIGNMENT);
		;
		this.koncludeFastMode.addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent e) {
				if (UBoxPanel.this.koncludeFastMode.isSelected()) {
					UDecideManager.fastKoncludeMode = true;
				} else {
					UDecideManager.fastKoncludeMode = false;
				}
			}
		});

		this.uAssertionListModel = new DefaultListModel<UtilityAssertion>();
		this.uAssertionList = new JList<UtilityAssertion>(this.uAssertionListModel);
		this.uAssertionList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		this.uAssertionList.setLayoutOrientation(JList.VERTICAL);
		this.uAssertionList.setVisibleRowCount(25);
		this.uAssertionList.setCellRenderer(new UtilityAssertionRenderer());
		UtilityAssertionListListener l = new UtilityAssertionListListener(this.uAssertionList);
		this.uAssertionList.addMouseListener(l);
		this.uAssertionList.getSelectionModel().addListSelectionListener(l);

		// initialise assertionPane
		this.uAssertionScrollPane = new JScrollPane(this.uAssertionList);
		new SmartScroller(this.uAssertionScrollPane);

		// fill button panel
		JPanel buttonPanel = new JPanel(new GridLayout(1, 4));
		buttonPanel.add(this.addUtilityAssertionButton);
		buttonPanel.add(this.removeUtilityAssertionButton);
		buttonPanel.add(UBoxPanel.startCalculationButton);
		buttonPanel.add(this.koncludeFastMode);

		JPanel assertionSplitter = new JPanel(new BorderLayout());
		assertionSplitter.add(this.uAssertionScrollPane, BorderLayout.CENTER);
		assertionSplitter.add(buttonPanel, BorderLayout.BEFORE_FIRST_LINE);
		assertionSplitter.setBorder(UDecideGUIElementFactory.getBorder("Utility Assertions for Attributes"));
		this.uAssertionScrollPane.setWheelScrollingEnabled(true);

		this.utilityAssertionPanel.add(assertionSplitter);
	}
}
